package aclInfoCollector.serialisator;

import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JLabel;
import javax.swing.JTextArea;

import framework.utils.Chrono;


import aclInfoCollector.utils.specialString.StringInterface;
import aclInfoCollector.utils.specialString.StringOperation;

import aclInfoCollector.filesAnalysers.code.classFile.ClassFileAnalyser;
import aclInfoCollector.filesAnalysers.code.javaFile.JavaAnalyser;
import aclInfoCollector.filesAnalysers.component.fractalFile.FractalAnalyser;
import aclInfoCollector.filesAnalysers.jarFile.JarAnalyser;

/**
 * La classe InfoBinder permet de relier les informations recoltées dans les
 * fichier fractal, jar, java et class
 * 
 * @version 1.0
 *@author Bendavid Olivier
 *@author Haderer Nicolas
 */

public class InfoBinder {

	private FractalAnalyser fractalAnalyser;
	private ClassFileAnalyser classAnalyser;
	private JavaAnalyser javaAnalyser;
	private JarAnalyser jarAnalyser;
	private ArrayList<String> components;
	private ArrayList<StringInterface> interfaces;
	private ArrayList<String> primitives;
	private ArrayList<String> classes;
	private HashMap<String, ArrayList<StringInterface>> componentsWithInterfaces;
	private HashMap<String, ArrayList<StringOperation>> interfacesWithOperations;
	private HashMap<String, ArrayList<String>> classesWithSuperTypes;
	private HashMap<String, ArrayList<String>> componentsWithSuperComps;
	private HashMap<String, ArrayList<String>> interfacesWithSuperInterFaces;
	private HashMap<String, ArrayList<String>> classesWithInterfaces;

	public InfoBinder() {
		initAttributes();
	}

	public InfoBinder(String path) {
		initAttributes();

		launchClassAnalysis(path);
		launchJavaAnalysis(path);
		launchFractalAnalysis(path);
		launchJarAnalysis(path);

		getInfos();

	}

	
	public void checkThatAllInterfacesDefExist()
	{
		int cpt = 0;
		for(String s : componentsWithInterfaces.keySet())
		{
			for(StringInterface si : componentsWithInterfaces.get(s))
			{
				if(!interfaces.contains(si.getSignature()))
						{
							cpt++;
						}
			}
			
		}
		System.out.println("nbe d' interfaces non defini : "+cpt+ "  nbe d'interfaces trouvées : "+interfaces.size());
		
		
	}
	
	
	public void addClasses(ArrayList<String> list) {
		for (String s : list) {
			if (!classes.contains(s)) {
				classes.add(s);
			}
		}
	}

	public void addClassesWithInterFaces(HashMap<String, ArrayList<String>> hm) {
		for (String key : hm.keySet()) {
			if (!classesWithInterfaces.containsKey(key)) {
				classesWithInterfaces.put(key, hm.get(key));
			} else {
				for (String s : hm.get(key)) {
					if (!classesWithInterfaces.get(key).contains(s)) {
						classesWithInterfaces.get(key).add(s);
					}
				}
			}

		}
	}

	public void addClassesWithSuperTypes(HashMap<String, ArrayList<String>> hm) {
		for (String key : hm.keySet()) {
			if (!classesWithSuperTypes.containsKey(key)) {
				classesWithSuperTypes.put(key, hm.get(key));
			} else {
				for (String s : hm.get(key)) {
					if (!classesWithSuperTypes.get(key).contains(s)) {
						classesWithSuperTypes.get(key).add(s);
					}
				}
			}
		}
	}

	public void addComponentsFractal(ArrayList<String> list) {
		for (String s : list) {
			if (!components.contains(s)) {
				components.add(s);
			}
		}
	}

	public void addComponentsWithInterfacesFractal(
			HashMap<String, ArrayList<StringInterface>> hm) {
		for (String key : hm.keySet()) {
			if (!componentsWithInterfaces.containsKey(key)) {
				componentsWithInterfaces.put(key, hm.get(key));
			} else {
				for (StringInterface s : hm.get(key)) {
					if (!componentsWithInterfaces.get(key).contains(s)) {
						componentsWithInterfaces.get(key).add(s);
					}
				}
			}
		}
	}

	public void addComponentsWithSuperCompFractal(
			HashMap<String, ArrayList<String>> hm) {
		componentsWithSuperComps = fractalAnalyser
				.getComponentsWithSuperComps();
		for (String key : hm.keySet()) {
			if (!componentsWithSuperComps.containsKey(key)) {
				componentsWithSuperComps.put(key, hm.get(key));
			} else {
				for (String s : hm.get(key)) {
					if (!componentsWithSuperComps.get(key).contains(s)) {
						componentsWithSuperComps.get(key).add(s);
					}
				}
			}
		}
	}

	public void addInterfacesFractal(ArrayList<StringInterface> list) {
		for (StringInterface s : list) {
			if (!interfaces.contains(s)) {
				interfaces.add(s);
			}
		}
	}

	public void addInterfacesWithOperations(
			HashMap<String, ArrayList<StringOperation>> hm) {
		for (String key : hm.keySet()) {
			if (!interfacesWithOperations.containsKey(key)) {
				interfacesWithOperations.put(key, hm.get(key));
			} else {
				for (StringOperation s : hm.get(key)) {
					if (!interfacesWithOperations.get(key).contains(s)) {
						interfacesWithOperations.get(key).add(s);
					}
				}
			}
		}
	}

	public void addInterfacesWithSuperInterfaces(
			HashMap<String, ArrayList<String>> hm) {
		for (String key : hm.keySet()) {
			if (!interfacesWithSuperInterFaces.containsKey(key)) {
				interfacesWithSuperInterFaces.put(key, hm.get(key));
			} else {
				for (String s : hm.get(key)) {
					if (!interfacesWithSuperInterFaces.get(key).contains(s)) {
						interfacesWithSuperInterFaces.get(key).add(s);
					}
				}
			}
		}
	}

	public void addPrimitives(ArrayList<String> list) {
		for (String s : list) {
			if (!primitives.contains(s)) {
				primitives.add(s);
			}
		}
	}

	/**
	 * @return the classFinder
	 */
	public ClassFileAnalyser getClassAnalyser() {
		return classAnalyser;
	}

	/**
	 * @return the classes
	 */
	public ArrayList<String> getClasses() {
		return classes;
	}
	/**
	 * @return the classesWithInterfaces
	 */
	public HashMap<String, ArrayList<String>> getClassesWithInterfaces() {
		return classesWithInterfaces;
	}

	/**
	 * @return the classesWithSuperTypes
	 */
	public HashMap<String, ArrayList<String>> getClassesWithSuperTypes() {
		return classesWithSuperTypes;
	}

	/**
	 * @return the components
	 */
	public ArrayList<String> getComponents() {
		return components;
	}

	/**
	 * @return the componentsWithInterfaces
	 */
	public HashMap<String, ArrayList<StringInterface>> getComponentsWithInterfaces() {
		return componentsWithInterfaces;
	}

	/**
	 * @return the componentsWithSuperComps
	 */
	public HashMap<String, ArrayList<String>> getComponentsWithSuperComps() {
		return componentsWithSuperComps;
	}

	/**
	 * @return the fractInfo
	 */
	public FractalAnalyser getFractalAnalyser() {
		return fractalAnalyser;
	}

	public void getInfoFromClassAnalyser() {
		addInterfacesWithSuperInterfaces(classAnalyser
				.getInterfacesWithSuperInterFaces());
		addClassesWithInterFaces(classAnalyser.getClassesWithInterfaces());
		addPrimitives(classAnalyser.getPrimitives());
		addClasses(classAnalyser.getClasses());
		addClassesWithSuperTypes(classAnalyser.getClassesWithSuperTypes());
		addInterfacesWithOperations(classAnalyser.getInterfacesWithOperations());
	}

	public void getInfoFromFractalAnalyser() {
		addInterfacesFractal(fractalAnalyser.getInterfaces());
		addComponentsFractal(fractalAnalyser.getComponents());
		addComponentsWithInterfacesFractal(fractalAnalyser
				.getComponentsWithInterfaces());
		addComponentsWithSuperCompFractal(fractalAnalyser
				.getComponentsWithSuperComps());

	}

	public void getInfoFromJarAnalyser() {
		addInterfacesWithSuperInterfaces(jarAnalyser.getClassAnalyser()
				.getInterfacesWithSuperInterFaces());
		addClassesWithInterFaces(jarAnalyser.getClassAnalyser()
				.getClassesWithInterfaces());
		addPrimitives(jarAnalyser.getClassAnalyser().getPrimitives());
		addClasses(jarAnalyser.getClassAnalyser().getClasses());
		addClassesWithSuperTypes(jarAnalyser.getClassAnalyser()
				.getClassesWithSuperTypes());
		addInterfacesWithOperations(jarAnalyser.getClassAnalyser()
				.getInterfacesWithOperations());

		addInterfacesWithSuperInterfaces(jarAnalyser.getJavaAnalyser()
				.getInterfacesWithSuperInterFaces());
		addClassesWithInterFaces(jarAnalyser.getJavaAnalyser()
				.getClassesWithInterfaces());
		addPrimitives(jarAnalyser.getJavaAnalyser().getPrimitives());
		addClasses(jarAnalyser.getJavaAnalyser().getClasses());
		addClassesWithSuperTypes(jarAnalyser.getJavaAnalyser()
				.getClassesWithSuperTypes());
		addInterfacesWithOperations(jarAnalyser.getJavaAnalyser()
				.getInterfacesWithOperations());

		addInterfacesFractal(jarAnalyser.getFractalAnalyser().getInterfaces());
		addComponentsFractal(jarAnalyser.getFractalAnalyser().getComponents());
		addComponentsWithInterfacesFractal(jarAnalyser.getFractalAnalyser()
				.getComponentsWithInterfaces());
		addComponentsWithSuperCompFractal(jarAnalyser.getFractalAnalyser()
				.getComponentsWithSuperComps());

	}

	public void getInfoFromJavaAnalyser() {
		addInterfacesWithSuperInterfaces(javaAnalyser
				.getInterfacesWithSuperInterFaces());
		addClassesWithInterFaces(javaAnalyser.getClassesWithInterfaces());
		addPrimitives(javaAnalyser.getPrimitives());
		addClasses(javaAnalyser.getClasses());
		addClassesWithSuperTypes(javaAnalyser.getClassesWithSuperTypes());
		addInterfacesWithOperations(javaAnalyser.getInterfacesWithOperations());
	}

	public void getInfos() {

		getInfoFromClassAnalyser();
		getInfoFromJavaAnalyser();
		getInfoFromFractalAnalyser();
		getInfoFromJarAnalyser();

	}

	public void getInfos(String path) {
		fractalAnalyser.launchAnalysis(path);
		fractalAnalyser.printSummary();
		javaAnalyser = new JavaAnalyser(path);
		javaAnalyser.printSummary();
		classAnalyser = new ClassFileAnalyser(path);
		classAnalyser.printSummary();
		jarAnalyser = new JarAnalyser(path);
		jarAnalyser.printSummary();
		getInfos();
	}

	/**
	 * @return the interfaces
	 */
	public ArrayList<StringInterface> getInterfaces() {
		return interfaces;
	}

	/**
	 * @return the interfacesWithOperations
	 */
	public HashMap<String, ArrayList<StringOperation>> getInterfacesWithOperations() {
		return interfacesWithOperations;
	}

	/**
	 * @return the interfacesWithSuperInterFaces
	 */
	public HashMap<String, ArrayList<String>> getInterfacesWithSuperInterFaces() {
		return interfacesWithSuperInterFaces;
	}

	/**
	 * @return the jarAnalyser
	 * 
	 */
	public JarAnalyser getJarAnalyser() {
		return jarAnalyser;
	}

	/**
	 * @return the javaFinder
	 */
	public JavaAnalyser getJavaAnalyser() {
		return javaAnalyser;
	}

	/**
	 * @return the primitives
	 */
	public ArrayList<String> getPrimitives() {
		return primitives;
	}

	public void initAttributes() {
		fractalAnalyser = new FractalAnalyser();
		classAnalyser = new ClassFileAnalyser();
		javaAnalyser = new JavaAnalyser();
		jarAnalyser = new JarAnalyser();
		components = new ArrayList<String>();
		classes = new ArrayList<String>();
		interfaces = new ArrayList<StringInterface>();
		componentsWithInterfaces = new HashMap<String, ArrayList<StringInterface>>();
		interfacesWithOperations = new HashMap<String, ArrayList<StringOperation>>();
		componentsWithSuperComps = new HashMap<String, ArrayList<String>>();
		classesWithSuperTypes = new HashMap<String, ArrayList<String>>();
		classesWithInterfaces = new HashMap<String, ArrayList<String>>();
		interfacesWithSuperInterFaces = new HashMap<String, ArrayList<String>>();
		primitives = new ArrayList<String>();
	}

	public void launchClassAnalysis(String path) {
		Chrono c = new Chrono();

		System.out.println("class files");
		c.start();
		classAnalyser = new ClassFileAnalyser(path);
		c.stop();
		c.printMilliSec();
	}

	public void launchClassAnalysis(String path, JLabel label) {
		Chrono c = new Chrono();

		System.out.println("class files");
		c.start();
		classAnalyser = new ClassFileAnalyser();
		classAnalyser.launchAnalysis(path, label);
		c.stop();
		c.printMilliSec();
	}

	public void launchFractalAnalysis(String path) {
		Chrono c = new Chrono();
		System.out.println("fractal files");
		c.start();
		fractalAnalyser.launchAnalysis(path);
		c.stop();
		c.printMilliSec();
	}

	public void launchFractalAnalysis(String path, JLabel label) {
		Chrono c = new Chrono();
		System.out.println("fractal files");
		c.start();
		fractalAnalyser.launchAnalysis(path, label);
		c.stop();
		c.printMilliSec();
	}

	public void launchJarAnalysis(String path) {
		Chrono c = new Chrono();
		System.out.println("jar files");
		c.start();
		jarAnalyser = new JarAnalyser(path);
		c.stop();
		c.printMilliSec();

	}

	public void launchJarAnalysis(String path, JLabel label) {
		Chrono c = new Chrono();
		System.out.println("jar files");
		c.start();
		jarAnalyser = new JarAnalyser();
		jarAnalyser.launchAnalysis(path, label);
		c.stop();
		c.printMilliSec();

	}

	public void launchJavaAnalysis(String path) {
		Chrono c = new Chrono();
		System.out.println("java files");
		c.start();
		javaAnalyser = new JavaAnalyser(path);
		c.stop();
		c.printMilliSec();
	}

	public void launchJavaAnalysis(String path, JLabel label) {
		Chrono c = new Chrono();
		System.out.println("java files");
		c.start();
		javaAnalyser = new JavaAnalyser();
		javaAnalyser.launchAnalysis(path, label);
		c.stop();
		c.printMilliSec();
	}
	

	public void launchJavaAnalysis(String path, JTextArea textArea) {
		Chrono c = new Chrono();
		System.out.println("java files");
		c.start();
		javaAnalyser = new JavaAnalyser();
		javaAnalyser.launchAnalysis(path, textArea);
		c.stop();
		c.printMilliSec();
	}

}
